/* Copyright (c) 2007 Pentaho Corporation.  All rights reserved.
 * This software was developed by Pentaho Corporation and is provided under the terms
 * of the GNU Lesser General Public License, Version 2.1. You may not use
 * this file except in compliance with the license. If you need a copy of the license,
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is Pentaho
 * Data Integration.  The Initial Developer is Pentaho Corporation.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to
 * the license for the specific language governing your rights and limitations.*/

/*
 *
 * Created on 4-apr-2003
 *
 */

package com.dc.trans.steps.binaryinput;

import java.util.List;
import java.util.Map;

import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.Counter;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.fileinput.FileInputList;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMeta;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;

import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;

import org.w3c.dom.Node;

import com.dc.trans.steps.datapack.DataPackMeta;

/**
 * Meta data for the Excel step.
 */
public class BinaryInputMeta extends BaseStepMeta implements StepMetaInterface {
	private static final String NO = "N";
	private static Class<?> PKG = BinaryInputMeta.class;
	private static final String YES = "Y";
	public final static int TYPE_TRIM_NONE = 0;
	public final static int TYPE_TRIM_LEFT = 1;
	public final static int TYPE_TRIM_RIGHT = 2;
	public final static int TYPE_TRIM_BOTH = 3;

	public final static String type_trim_code[] = { "none", "left", "right",
			"both" };

	public static final String STRING_SEPARATOR = " \t --> ";

	/**
	 * The filenames to load or directory in case a filemask was set.
	 */
	private String fileName[];

	/**
	 * The regular expression to use (null means: no mask)
	 */
	private String fileMask[];

	private String fileRequired[];

	private boolean encode;
	private boolean isFormatMatch;

	private long sizeLimit;

	public BinaryInputMeta() {
		super(); // allocate BaseStepMeta
	}

	// liangxin
	private String acceptingField;
	private String acceptingStepName;
	//private StepMeta acceptingStep;
	private boolean acceptingFilenames;

	/**
	 * @return Returns the fileMask.
	 */
	public String[] getFileMask() {
		return fileMask;
	}

	/**
	 * @param fileMask
	 *            The fileMask to set.
	 */
	public void setFileMask(String[] fileMask) {
		this.fileMask = fileMask;
	}

	/**
	 * @return Returns the fileName.
	 */
	public String[] getFileName() {
		return fileName;
	}

	/**
	 * @param fileName
	 *            The fileName to set.
	 */
	public void setFileName(String[] fileName) {
		this.fileName = fileName;
	}

	public void loadXML(Node stepnode, List<DatabaseMeta> databases,
			Map<String, Counter> counters) throws KettleXMLException {
		readData(stepnode);
	}

	public Object clone() {
		BinaryInputMeta retval = (BinaryInputMeta) super.clone();
		int nrfiles = fileName.length;
		retval.allocate(nrfiles);
		for (int i = 0; i < nrfiles; i++) {
			retval.fileName[i] = fileName[i];
			retval.fileMask[i] = fileMask[i];
			retval.fileRequired[i] = fileRequired[i];
		}
		return retval;
	}

	private void readData(Node stepnode) throws KettleXMLException {
		try {
			Node filenode = XMLHandler.getSubNode(stepnode, "file");
			int nrfiles = XMLHandler.countNodes(filenode, "name");
			acceptingFilenames = YES.equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "accept_filenames"));
			acceptingField = XMLHandler.getTagValue(stepnode, "accept_field");
			acceptingStepName = XMLHandler.getTagValue(stepnode,"accept_stepname");
			allocate(nrfiles);
			for (int i = 0; i < nrfiles; i++) {
				Node filenamenode = XMLHandler.getSubNodeByNr(filenode, "name",i);
				Node filemasknode = XMLHandler.getSubNodeByNr(filenode,"filemask", i);
				fileName[i] = XMLHandler.getNodeValue(filenamenode);
				fileMask[i] = XMLHandler.getNodeValue(filemasknode);
			}
			encode = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode,"encode"));
			isFormatMatch = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode,"isFormatMatch"));
			sizeLimit = Const.toLong(XMLHandler.getTagValue(stepnode,"size_limit"), 0);
		} catch (Exception e) {
			throw new KettleXMLException("Unable to read step information from XML", e);
		}
	}

	public void allocate(int nrfiles) {
		fileName = new String[nrfiles];
		fileMask = new String[nrfiles];
		fileRequired = new String[nrfiles];
	}

	public void setDefault() {
		int nrfiles = 0;
		int nrfields = 0;
		int nrsheets = 0;
		encode = true;
		sizeLimit = 0;
		allocate(nrfiles);
		for (int i = 0; i < nrfiles; i++) {
			fileName[i] = "filename" + (i + 1);
			fileMask[i] = "";
			fileRequired[i] = NO;
		}
		for (int i = 0; i < nrfields; i++) {
		}
	}

	public String getXML() {
		StringBuffer retval = new StringBuffer(1024);
		/*
		 * Describe the files to read
		 */
		retval.append("    <file>").append(Const.CR);
		for (int i = 0; i < fileName.length; i++) {
			retval.append("      ").append(XMLHandler.addTagValue("name", fileName[i]));
			retval.append("      ").append(XMLHandler.addTagValue("filemask", fileMask[i]));
			retval.append("      ").append(XMLHandler.addTagValue("file_required", fileRequired[i]));
		}
		retval.append("    </file>").append(Const.CR);
		retval.append("    " + XMLHandler.addTagValue("encode", encode));
		retval.append("    " + XMLHandler.addTagValue("size_limit", sizeLimit));
		retval.append("    ").append(
				XMLHandler.addTagValue("accept_filenames", acceptingFilenames));
		retval.append("    ").append(XMLHandler.addTagValue("accept_field", acceptingField));
		retval.append("    ").append(XMLHandler.addTagValue("isFormatMatch", isFormatMatch));
//		retval.append("    ")
//				.append(
//						XMLHandler.addTagValue("accept_stepname",
//								(acceptingStep != null ? acceptingStep
//										.getName() : "")));
		return retval.toString();
	}

	public void readRep(Repository rep, long id_step,
			List<DatabaseMeta> databases, Map<String, Counter> counters)
			throws KettleException {
		
	}

	

	public FileInputList getBinaryFileList(VariableSpace space) {
		return FileInputList.createFileList(space, fileName, fileMask,fileRequired,new String[] { "N" });
	}

	public void getFields(RowMetaInterface row, String name,
			RowMetaInterface[] info, StepMeta nextStep, VariableSpace space)
			throws KettleStepException {
		ValueMetaInterface vfname = new ValueMeta("filename",ValueMetaInterface.TYPE_STRING);
		vfname.setLength(100);
		vfname.setTrimType(ValueMetaInterface.TRIM_TYPE_BOTH);

		ValueMetaInterface vfcontent = null;
		if (encode) {
			vfcontent = new ValueMeta("filecontent",ValueMetaInterface.TYPE_STRING);
			vfcontent.setLength(9999999);
			vfcontent.setLargeTextField(true);
		} else {
			vfcontent = new ValueMeta("filecontent",ValueMetaInterface.TYPE_BINARY);
		}
		//liangxin
		ValueMetaInterface isformatmatch = new ValueMeta("isformatmatch",ValueMetaInterface.TYPE_BOOLEAN);		
		// <--liangxin
		/*
		ValueMetaInterface vfpath = new ValueMeta("filepath",
				ValueMetaInterface.TYPE_STRING);
		vfpath.setLength(100);
		vfpath.setTrimType(ValueMetaInterface.TRIM_TYPE_BOTH);
		*/
		//-->liangxin
		row.addValueMeta(vfname);
		row.addValueMeta(vfcontent);
		row.addValueMeta(isformatmatch);		
		//<--liangxin
		//row.addValueMeta(vfpath);
		//-->liangxin
	}

	public final static int getTrimTypeByCode(String tt) {
		if (tt != null) {
			for (int i = 0; i < type_trim_code.length; i++) {
				if (type_trim_code[i].equalsIgnoreCase(tt))
					return i;
			}
		}
		return 0;
	}

	public final static String getTrimTypeCode(int i) {
		if (i < 0 || i >= type_trim_code.length)
			return type_trim_code[0];
		return type_trim_code[i];
	}

	public void check(List<CheckResultInterface> remarks, TransMeta transMeta,
			StepMeta stepMeta, RowMetaInterface prev, String input[],
			String output[], RowMetaInterface info) {
		CheckResult cr;

		// See if we get input...
		if (input.length > 0) {

		} else {
			cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK, BaseMessages
					.getString(PKG,"ExcelInputMeta.CheckResult.NoInputOk"),
					stepMeta);
			remarks.add(cr);
		}
	}

	public StepInterface getStep(StepMeta stepMeta,
			StepDataInterface stepDataInterface, int cnr, TransMeta transMeta,
			Trans trans) {
		return new BinaryInput(stepMeta, stepDataInterface, cnr, transMeta,
				trans);
	}

	public StepDataInterface getStepData() {
		return new BinaryInputData();
	}

	public String[] getFileRequired() {
		return fileRequired;
	}

	public void setFileRequired(String[] fileRequired) {
		this.fileRequired = fileRequired;
	}

	public boolean isEncode() {
		return encode;
	}

	public void setEncode(boolean encode) {
		this.encode = encode;
	}

	public long getSizeLimit() {
		return sizeLimit;
	}

	public void setSizeLimit(long sizeLimit) {
		this.sizeLimit = sizeLimit;
	}

	public String getAcceptingField() {
		return acceptingField;
	}

	public void setAcceptingField(String acceptingField) {
		this.acceptingField = acceptingField;
	}

//	public StepMeta getAcceptingStep() {
//		return acceptingStep;
//	}
//
//	public void setAcceptingStep(StepMeta acceptingStep) {
//		this.acceptingStep = acceptingStep;
//	}

	public boolean isAcceptingFilenames() {
		return acceptingFilenames;
	}

	public void setAcceptingFilenames(boolean acceptingFilenames) {
		this.acceptingFilenames = acceptingFilenames;
	}

	public String getAcceptingStepName() {
		return acceptingStepName;
	}

	public void setAcceptingStepName(String acceptingStepName) {
		this.acceptingStepName = acceptingStepName;
	}

	public boolean isFormatMatch() {
		return isFormatMatch;
	}

	public void setFormatMatch(boolean isFormatMatch) {
		this.isFormatMatch = isFormatMatch;
	}

	public void readRep(Repository rep, ObjectId id_step,
			List<DatabaseMeta> databases, Map<String, Counter> counters)
			throws KettleException {
		try {
			int nrfiles = rep.countNrStepAttributes(id_step, "file_name");
			allocate(nrfiles);
			// System.out.println("Counted "+nrfiles+" files to read and
			// "+nrsheets+" sheets, "+nrfields+" fields.");
			for (int i = 0; i < nrfiles; i++) {
				fileName[i] = rep.getStepAttributeString(id_step, i,"file_name");
				fileMask[i] = rep.getStepAttributeString(id_step, i,"file_mask");
				fileRequired[i] = rep.getStepAttributeString(id_step, i,"file_required");
			}
			sizeLimit = rep.getStepAttributeInteger(id_step, "size_limit");
			encode = rep.getStepAttributeBoolean(id_step, "encode");
			acceptingFilenames = rep.getStepAttributeBoolean(id_step,"accept_filenames");
			acceptingField = rep.getStepAttributeString(id_step, "accept_field");
			acceptingStepName = rep.getStepAttributeString(id_step,"accept_stepname");
			isFormatMatch = rep.getStepAttributeBoolean(id_step, "isFormatMatch");
		} catch (Exception e) {
			throw new KettleException("Unexpected error reading step information from the repository",e);
		}
		
	}

	public void saveRep(Repository rep, ObjectId id_transformation,
			ObjectId id_step) throws KettleException {
		try {
			for (int i = 0; i < fileName.length; i++) {
				rep.saveStepAttribute(id_transformation, id_step, i,"file_name", fileName[i]);
				rep.saveStepAttribute(id_transformation, id_step, i,"file_mask", fileMask[i]);
				rep.saveStepAttribute(id_transformation, id_step, i,"file_required", fileRequired[i]);
			}
			rep.saveStepAttribute(id_transformation, id_step, "size_limit",sizeLimit);
			rep.saveStepAttribute(id_transformation, id_step, "encode", encode);
			rep.saveStepAttribute(id_transformation, id_step,"accept_filenames", acceptingFilenames);
			rep.saveStepAttribute(id_transformation, id_step, "accept_field",acceptingField);
			rep.saveStepAttribute(id_transformation, id_step, "isFormatMatch",isFormatMatch);
//			rep.saveStepAttribute(id_transformation, id_step,"accept_stepname", (acceptingStep != null ? acceptingStep.getName() : ""));
		} catch (Exception e) {
			throw new KettleException("Unable to save step information to the repository for id_step="+ id_step, e);
		}
	}

//	public String getLookupStepname() {
//		if (acceptingFilenames && acceptingStep != null
//				&& !Const.isEmpty(acceptingStep.getName()))
//			return acceptingStep.getName();
//		return null;
//	}
//
//	public String[] getInfoSteps() {
//		if (acceptingFilenames && acceptingStep != null) {
//			return new String[] { acceptingStep.getName() };
//		}
//		return super.getInfoSteps();
//	}

}